// Fill out your copyright notice in the Description page of Project Settings.

#include "Isalong2.h"
#include "CGameManager.h"
#include "EnvironmentManager.h"


void AEnvironmentManager::UpdateEnvironmentTick()
{
	_skyLight->RecaptureSky();
	if (TimeOfDay>600&&TimeOfDay<1800)
	{
		_dayLight->SetVisibility(true);
		_nightLight->SetVisibility(false);
	}
	else
	{
		_dayLight->SetVisibility(false);
		_nightLight->SetVisibility(true);
	}
}

void AEnvironmentManager::DayTimeUpdate(float DeltaTime)
{
	float newTime= DeltaTime / 60 * 2400 / DayLength + TimeOfDay;
	if (newTime>=2400)
	{
		newTime = 0;
		_DaysTime++;
	}
	if (newTime<0)
	{
		newTime = 2399;
	}
	TimeOfDay = newTime;
}

void AEnvironmentManager::CloudDensityUpdate()
{
	if (_DaysTime>=_densityMapHeight)
	{
		_DaysTime = 0;
	}
	FColor data = _pixelData[_DaysTime*_densityMapWidth + (int)(TimeOfDay / 2400.0f * _densityMapWidth)];
	CloudDensityTarget = (data.R+data.G+data.B)/ 255.0f;  // for the cloud max is 3
}

// Sets default values
AEnvironmentManager::AEnvironmentManager()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	_dayLight = CreateDefaultSubobject<UDirectionalLightComponent>(TEXT("DayLight"));
	_dayLight->SetWorldRotation(FRotator(-5.778893, -101.359093, 0));
	_dayLight->SetMobility(EComponentMobility::Movable);
	_dayLight->SetIntensity(40);
	_dayLight->SetLightColor(FLinearColor(0.933, 0.565, 0.118,1),false);
	_dayLight->SetEnableLightShaftBloom(true);
	_dayLight->SetBloomScale(0.03);
	_dayLight->SetBloomThreshold(4.0);
	_dayLight->SetBloomTint(FLinearColor(0.933, 0.565, 0.118, 1).ToFColor(false));

	_nightLight = CreateDefaultSubobject<UDirectionalLightComponent>(TEXT("NightLight"));
	_nightLight->SetWorldRotation(FRotator(42.867134, 51.290955,0));
	_nightLight->SetMobility(EComponentMobility::Movable);
	_nightLight->SetIntensity(0.775527);
	_nightLight->SetLightColor(FLinearColor(0.478, 0.592, 1.0, 1), false);
	_nightLight->SetEnableLightShaftBloom(true);
	_nightLight->SetBloomScale(0.03);
	_nightLight->SetBloomThreshold(4.0f);
	_nightLight->SetBloomTint(FColor(185, 187, 188));
	UMaterial* lightFunctionMaterial = LoadObject<UMaterial>(NULL, TEXT("Material'/Game/UltraDynamicSky/Materials/Cloud_Shadows.Cloud_Shadows'"));
	_nightLight->SetLightFunctionMaterial(lightFunctionMaterial);
	_nightLight->SetLightFunctionScale(FVector(120000.0, 120000.0, 120000.0));
	_nightLight->SetLightFunctionFadeDistance(56915.1875);
	_nightLight->SetLightFunctionDisabledBrightness(0.681416);

	_expHightFog = CreateDefaultSubobject<UExponentialHeightFogComponent>(TEXT("Fog"));
	_expHightFog->SetFogInscatteringColor(FLinearColor(0.933318, 0.282851, 0.123307));
	_expHightFog->SetFogHeightFalloff(1.588905);
	_expHightFog->SetFogMaxOpacity(0.867257);
	_expHightFog->SetDirectionalInscatteringExponent(2.548673);
	_expHightFog->SetDirectionalInscatteringStartDistance(1.271775);
	_expHightFog->SetDirectionalInscatteringColor(FLinearColor(0.933, 0.283, 0.123));

	_skyLight = CreateDefaultSubobject<USkyLightComponent>(TEXT("SkyLight"));
	_skyLight->SetMobility(EComponentMobility::Movable);
	_skyLight->SetIntensity(0.5);

	_dynamicSkySphere = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Sky"));
	_dynamicSkySphere->SetCastShadow(false);

	_sunRoot = CreateDefaultSubobject<UArrowComponent>(TEXT("SunRoot"));

	SetRootComponent(_dynamicSkySphere);
	_sunRoot->AttachTo(_dynamicSkySphere);

	// load curve
	_sunLightIstCloudDensity = LoadObject<UCurveFloat>(NULL, TEXT("CurveFloat'/Game/BrainInVst/Manager/_EvtTime/DayLightInst_CloudDesnity.DayLightInst_CloudDesnity'"));
	_sunLightDayNight = LoadObject<UCurveFloat>(NULL, TEXT("CurveFloat'/Game/BrainInVst/Manager/_EvtTime/DayNightSunInstCurve.DayNightSunInstCurve'"));
	_sunDistributionExponent = LoadObject<UCurveFloat>(NULL, TEXT("CurveFloat'/Game/BrainInVst/Manager/_EvtTime/DayLightShadowDE.DayLightShadowDE'"));
	_moonLightCloudIst = LoadObject<UCurveFloat>(NULL, TEXT("CurveFloat'/Game/BrainInVst/Manager/_EvtTime/NightInst_Cloud.NightInst_Cloud'"));
	_eFogDayNight = LoadObject<UCurveFloat>(NULL, TEXT("CurveFloat'/Game/BrainInVst/Manager/_EvtTime/Day_EFog_Curve.Day_EFog_Curve'"));
}

// Called when the game starts or when spawned
void AEnvironmentManager::BeginPlay()
{
	Super::BeginPlay();
	_cloudDensity = LoadObject<UTexture2D>(NULL, TEXT("Texture2D'/Game/BrainInVst/Curve/CloudDensity.CloudDensity'"));
	FTexture2DMipMap* tempMinMap = &_cloudDensity->PlatformData->Mips[0];
	_densityMapWidth = tempMinMap->SizeX;
	_densityMapHeight = tempMinMap->SizeY;
	_cloudDensity->PlatformData->Mips[0].BulkData.GetCopy((void**)&_pixelData);
}

// Called every frame
void AEnvironmentManager::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );
	_tickTimeRemain += DeltaTime;
	if (_tickTimeRemain>_tickTimeEach)
	{
		_tickTimeRemain = 0;
		UpdateEnvironmentTick();
	}

	DayTimeUpdate(DeltaTime);
	CloudDensityUpdate();

	// update shadow casd
	_dayLight->CascadeDistributionExponent = _sunDistributionExponent->GetFloatValue(TimeOfDay);
	_dayLight->MarkRenderStateDirty();

	// update day night light
	float dayInst = _sunLightIstCloudDensity->GetFloatValue(CloudDensity)-_sunLightDayNight->GetFloatValue(TimeOfDay);
	dayInst = dayInst < 0 ? 0 : dayInst;
	float moonInst = _moonLightCloudIst->GetFloatValue(CloudDensity);

	_dayLight->SetIntensity(dayInst);
	// may not work
	//_nightLight->SetIntensity(moonInst);
	
	// update fog
	_expHightFog->SetFogDensity(_eFogDayNight->GetFloatValue(TimeOfDay));
	
}

